// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.ai;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Stack;
import zombie.ai.states.ThumpState;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoPlayer;
import zombie.characters.IsoZombie;
import zombie.characters.Stance;
import zombie.characters.Stats;
import zombie.characters.SurvivorDesc;
import zombie.characters.SurvivorGroup;
import zombie.iso.IsoMovingObject;
import zombie.iso.LosUtil;
import zombie.iso.Vector2;
import zombie.iso.Vector3;

public final class GameCharacterAIBrain {
    private final IsoGameCharacter character;
    public final ArrayList<IsoGameCharacter> spottedCharacters = new ArrayList();
    public boolean StepBehaviors;
    public Stance stance;
    public boolean controlledByAdvancedPathfinder;
    public boolean isInMeta;
    public final HashMap<Vector3, ArrayList<Vector3>> BlockedMemories = new HashMap();
    public final Vector2 AIFocusPoint = new Vector2();
    public final Vector3 nextPathTarget = new Vector3();
    public IsoMovingObject aiTarget;
    public boolean NextPathNodeInvalidated;
    public final AIBrainPlayerControlVars HumanControlVars = new AIBrainPlayerControlVars();
    String order;
    public ArrayList<IsoZombie> teammateChasingZombies = new ArrayList();
    public ArrayList<IsoZombie> chasingZombies = new ArrayList();
    public boolean allowLongTermTick = true;
    public boolean isAI = false;
    static ArrayList<IsoZombie> tempZombies = new ArrayList();
    static IsoGameCharacter compare;
    private static final Stack<Vector3> Vectors = new Stack();

    public IsoGameCharacter getCharacter() {
        return this.character;
    }

    public GameCharacterAIBrain(IsoGameCharacter _character) {
        this.character = _character;
    }

    public void update() {
    }

    public void postUpdateHuman(IsoPlayer isoPlayer) {
    }

    public String getOrder() {
        return this.order;
    }

    public void setOrder(String _order) {
        this.order = _order;
    }

    public SurvivorGroup getGroup() {
        return this.character.getDescriptor().getGroup();
    }

    public int getCloseZombieCount() {
        this.character.getStats();
        return Stats.NumCloseZombies;
    }

    public IsoZombie getClosestChasingZombie(boolean recurse) {
        IsoZombie isoZombie0 = null;
        float float0 = 1.0E7F;

        for (int int0 = 0; int0 < this.chasingZombies.size(); int0++) {
            IsoZombie isoZombie1 = (IsoZombie)this.chasingZombies.get(int0);
            float float1 = isoZombie1.DistTo(this.character);
            if (isoZombie1.isOnFloor()) {
                float1 += 2.0F;
            }

            if (!LosUtil.lineClearCollide(
                    (int)isoZombie1.x, (int)isoZombie1.y, (int)isoZombie1.z, (int)this.character.x, (int)this.character.y, (int)this.character.z, false
                )
                && isoZombie1.getStateMachine().getCurrent() != ThumpState.instance()
                && float1 < float0
                && isoZombie1.target == this.character) {
                float0 = float1;
                isoZombie0 = (IsoZombie)this.chasingZombies.get(int0);
            }
        }

        if (isoZombie0 == null && recurse) {
            for (int int1 = 0; int1 < this.getGroup().Members.size(); int1++) {
                IsoGameCharacter isoGameCharacter0 = ((SurvivorDesc)this.getGroup().Members.get(int1)).getInstance();
                IsoZombie isoZombie2 = isoGameCharacter0.getGameCharacterAIBrain().getClosestChasingZombie(false);
                if (isoZombie2 != null) {
                    float float2 = isoZombie2.DistTo(this.character);
                    if (float2 < float0) {
                        float0 = float2;
                        isoZombie0 = isoZombie2;
                    }
                }
            }
        }

        if (isoZombie0 == null && recurse) {
            for (int int2 = 0; int2 < this.spottedCharacters.size(); int2++) {
                IsoGameCharacter isoGameCharacter1 = (IsoGameCharacter)this.spottedCharacters.get(int2);
                IsoZombie isoZombie3 = isoGameCharacter1.getGameCharacterAIBrain().getClosestChasingZombie(false);
                if (isoZombie3 != null) {
                    float float3 = isoZombie3.DistTo(this.character);
                    if (float3 < float0) {
                        float0 = float3;
                        isoZombie0 = isoZombie3;
                    }
                }
            }
        }

        return isoZombie0 != null && isoZombie0.DistTo(this.character) > 30.0F ? null : isoZombie0;
    }

    public IsoZombie getClosestChasingZombie() {
        return this.getClosestChasingZombie(true);
    }

    public ArrayList<IsoZombie> getClosestChasingZombies(int num) {
        tempZombies.clear();
        Object object = null;
        float float0 = 1.0E7F;

        for (int int0 = 0; int0 < this.chasingZombies.size(); int0++) {
            IsoZombie isoZombie = (IsoZombie)this.chasingZombies.get(int0);
            float float1 = isoZombie.DistTo(this.character);
            if (!LosUtil.lineClearCollide(
                (int)isoZombie.x, (int)isoZombie.y, (int)isoZombie.z, (int)this.character.x, (int)this.character.y, (int)this.character.z, false
            )) {
                tempZombies.add(isoZombie);
            }
        }

        compare = this.character;
        tempZombies.sort((isoZombie0, isoZombie1) -> {
            float float0x = compare.DistTo(isoZombie0);
            float float1x = compare.DistTo(isoZombie1);
            if (float0x > float1x) {
                return 1;
            } else {
                return float0x < float1x ? -1 : 0;
            }
        });
        int int1 = num - tempZombies.size();
        if (int1 > tempZombies.size() - 2) {
            int1 = tempZombies.size() - 2;
        }

        for (int int2 = 0; int2 < int1; int2++) {
            tempZombies.remove(tempZombies.size() - 1);
        }

        return tempZombies;
    }

    public void AddBlockedMemory(int ttx, int tty, int ttz) {
        synchronized (this.BlockedMemories) {
            Vector3 vector30 = new Vector3((float)((int)this.character.x), (float)((int)this.character.y), (float)((int)this.character.z));
            if (!this.BlockedMemories.containsKey(vector30)) {
                this.BlockedMemories.put(vector30, new ArrayList());
            }

            ArrayList arrayList = (ArrayList)this.BlockedMemories.get(vector30);
            Vector3 vector31 = new Vector3((float)ttx, (float)tty, (float)ttz);
            if (!arrayList.contains(vector31)) {
                arrayList.add(vector31);
            }
        }
    }

    public boolean HasBlockedMemory(int lx, int ly, int lz, int x, int y, int z) {
        synchronized (this.BlockedMemories) {
            synchronized (Vectors) {
                Vector3 vector30;
                if (Vectors.isEmpty()) {
                    vector30 = new Vector3();
                } else {
                    vector30 = (Vector3)Vectors.pop();
                }

                Vector3 vector31;
                if (Vectors.isEmpty()) {
                    vector31 = new Vector3();
                } else {
                    vector31 = (Vector3)Vectors.pop();
                }

                vector30.x = (float)lx;
                vector30.y = (float)ly;
                vector30.z = (float)lz;
                vector31.x = (float)x;
                vector31.y = (float)y;
                vector31.z = (float)z;
                if (!this.BlockedMemories.containsKey(vector30)) {
                    Vectors.push(vector30);
                    Vectors.push(vector31);
                    return false;
                }

                if (((ArrayList)this.BlockedMemories.get(vector30)).contains(vector31)) {
                    Vectors.push(vector30);
                    Vectors.push(vector31);
                    return true;
                }

                Vectors.push(vector30);
                Vectors.push(vector31);
            }

            return false;
        }
    }

    public void renderlast() {
    }
}
